package cn.edu.scau.cmi.ema.service.base;

import cn.edu.scau.cmi.ema.base.CmiPagination;
import cn.edu.scau.cmi.ema.util.CmiEntityUtil;
import cn.edu.scau.cmi.ema.util.CmiHibernateProxyUtil;
import cn.edu.scau.cmi.ema.util.CmiSetUtil;
import cn.edu.scau.cmi.ema.util.CmiStringUtil;
import org.springframework.stereotype.Service;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

@Service("CmiPaginationService")
public class CmiPaginationService {

//	TODO 2021-05-30 需要继续完善。     更新分页对象，但是不能统一更新不同类型对象的基本属性集合，需要在具体的分页对象中覆盖这个方法。
	public CmiPagination updatePagination(CmiPagination cmiPagination, int totalElements) {


//		1. 更新记录总数totalRecord
		cmiPagination.setTotalRecords(totalElements);

//		2. 更新currentPagination, inputPagination, clickPagination
//		（1）第一次进入list页面的时候，currentPagination是-1，设置currentPagination是-1；clickPagination和inputPagination保持默认值不变；
//		（2）优先查看clickPagination，如果不是-1；表示是点击进入，将clickPagination复制给currentPagination，然后，再将clickPagination设置为-1；
//		（3）如果currentPagination不是-1，clickPagination是-1，表示是输入的页面进入，currentPagination设置为inputPagination;
//
//		if (cmiPagination.getCurrentPagination() == -1) {
//			cmiPagination.setCurrentPagination(1);
//		}else

//		2021年6月14号：app请求没有clickPagination，或者是其他的内容，暂时不确定，有待查看
//
//
//		if (cmiPagination.getClickPagination() != -1) {
////			cmiPagination.setCurrentPagination(cmiPagination.getClickPagination());
////			cmiPagination.setClickPagination(-1);
//			cmiPagination.setInputPagination(-1);
//		}else {
////			cmiPagination.setClickPagination(cmiPagination.getClickPagination());
////			cmiPagination.setCurrentPagination(cmiPagination.getInputPagination());
////			当前输入的页面还是要保持，在页面中显示。
//		}

//		2. 更新currentPagination


		if(cmiPagination.getInputPagination() != -1) {
			cmiPagination.setCurrentPagination(cmiPagination.getInputPagination() );
		}

		if(cmiPagination.getFirstPagination() != null) {
			cmiPagination.setCurrentPagination(1);
			cmiPagination.setInputPagination(-1);
		}
		if(cmiPagination.getLastPagination() != null) {
			cmiPagination.setCurrentPagination(cmiPagination.getTotalPaginations());
			cmiPagination.setInputPagination(-1);
		}

		if(cmiPagination.getPreviousPagination() != null) {
			cmiPagination.setCurrentPagination(cmiPagination.getCurrentPagination() - 1);
			cmiPagination.setInputPagination(-1);
		}
		if(cmiPagination.getNextPagination() != null) {
			cmiPagination.setCurrentPagination(cmiPagination.getCurrentPagination() + 1);
			cmiPagination.setInputPagination(-1);
		}

		if (cmiPagination.getTotalRecords() == 0) {
			cmiPagination.setTotalPaginations(1);
		} else if (cmiPagination.getTotalRecords() % cmiPagination.getPaginationSize() == 0) {
			cmiPagination.setTotalPaginations(cmiPagination.getTotalRecords() / cmiPagination.getPaginationSize());
		} else {
			cmiPagination.setTotalPaginations(cmiPagination.getTotalRecords() / cmiPagination.getPaginationSize() + 1);
		}

//		4. 更新页面的游标
		if(cmiPagination.getTotalPaginations() <=  CmiPagination.MAX_PAGE_CURSOR_SIZE + 1) {   //左边的区间和右边的区间重叠
			cmiPagination.setSearchBeginCursor(1);
			cmiPagination.setSearchEndCursor(cmiPagination.getTotalPaginations());
		}else {
			if(cmiPagination.getTotalPaginations() - cmiPagination.getCurrentPagination()  < CmiPagination.MAX_PAGE_CURSOR_SIZE/2) {    //在右边的区间
				cmiPagination.setSearchBeginCursor(cmiPagination.getTotalPaginations() - CmiPagination.MAX_PAGE_CURSOR_SIZE);
				cmiPagination.setSearchEndCursor(cmiPagination.getTotalPaginations());
			}else if (cmiPagination.getCurrentPagination() - 1 < CmiPagination.MAX_PAGE_CURSOR_SIZE/2) {  //在左边的区间
				cmiPagination.setSearchBeginCursor(1);
				cmiPagination.setSearchEndCursor(cmiPagination.getSearchBeginCursor() + CmiPagination.MAX_PAGE_CURSOR_SIZE);
			}else {//在中间的区间
				cmiPagination.setSearchBeginCursor(cmiPagination.getCurrentPagination() - CmiPagination.MAX_PAGE_CURSOR_SIZE/2);
				cmiPagination.setSearchEndCursor(cmiPagination.getCurrentPagination() + CmiPagination.MAX_PAGE_CURSOR_SIZE/2);
			}
		}
		return cmiPagination;
	}

	/* 更新jsp中的分页数据。
	 * 实体的引用属性分页
	 * 不需要CmiPagination对象！！！！！！，采用默认的pagination属性即可*/
	public <T> T getReferencePaginationEntity(T entity, CmiPagination pagination) {

		Map<String, Class<?>> referencePropertyPaginationMap = pagination.getPropertyTypeMap();//.getReferencePropertyPaginationMap();
		Set<Entry<String, Class<?>>> references = referencePropertyPaginationMap.entrySet();
		for(Entry<String, Class<?>> ref : references) {

			String propertyName = ref.getKey();
			Class<?> propertyClass = ref.getValue();

			if(propertyClass == Set.class) {
				try {
					Method getMethod = entity.getClass().getMethod("get"+ CmiStringUtil.convertFirstCharToUpper(propertyName));
					Set allRederenceObjects = (Set) getMethod.invoke(entity);

					if(allRederenceObjects != null && allRederenceObjects.size() > 0) {
						Set paginationRederenceObjects = CmiSetUtil.getInstances(allRederenceObjects, 10);
						Method setMethod = entity.getClass().getMethod("set"+ CmiStringUtil.convertFirstCharToUpper(propertyName), Set.class);
						setMethod.invoke(entity, paginationRederenceObjects);
					}

				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (SecurityException e) {
					e.printStackTrace();
				}
				catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
//			更新分页对象

		}
		return entity;
	}

	   /*
		 * 原来在CmiPagination 根据需要分页的对象，设置属性，目前是PSON中使用。应该是对一个实体进行分页 有点拗口，应该是Pson的功能。
		 * 2021年6月14号：对象的属性分页
		 * 如果是集合对象，就设置的记录数量和总的分页数量
		 * 如果是对象，就设置对象中的集合属性的分页
		 */
	    public CmiPagination getEntityPagination(Object object) {
	    	CmiPagination cmiPagination = new CmiPagination();
	        if (object instanceof Collection<?>) {
	            int myTotalRecords = ((Collection<?>) object).size();
	            cmiPagination.setTotalRecords(myTotalRecords);
	            int myTotalPages = 0;
	            if (myTotalRecords % cmiPagination.getPaginationSize() == 0) {
	                myTotalPages = myTotalRecords / cmiPagination.getPaginationSize();
	            } else {
	                myTotalPages = myTotalRecords / cmiPagination.getPaginationSize() + 1;
	            }
	            cmiPagination.setTotalPaginations(myTotalPages);
	        } else {
	            object = CmiHibernateProxyUtil.deproxy(object);
//	            迭代所有的集合属性并分页
	            Field[] fields = object.getClass().getDeclaredFields();
	            Field.setAccessible(fields, true);
	            for (Field field : fields) {
	                Object fieldObject;
	                try {
	                    String fieldName = field.getName();
	                    fieldObject = field.get(object);
	                    if (!(fieldObject instanceof Collection<?>))
	                        continue;

	                    if (!cmiPagination.getReferencePropertyPaginationMap().containsKey(fieldName)) {
							// 是集合就注册 CmiAttributePagination
	                    	cmiPagination.getReferencePropertyPaginationMap().put(fieldName, new CmiPagination());
						}
						@SuppressWarnings("unchecked")
	                    Collection<Object> objCollection = (Collection<Object>) fieldObject;

	                    int fieldTotalRecords = objCollection.size();

//	                    System.out.println("---------" + fieldName);
	                    CmiPagination fieldPagination = cmiPagination.getReferencePropertyPaginationMap().get(fieldName);

	                    fieldPagination.setTotalRecords(fieldTotalRecords);
	                    int fieldTotalPages = 0;
	                    if (fieldTotalRecords % fieldPagination.getPaginationSize() == 0) {
	                        fieldTotalPages = fieldTotalRecords / fieldPagination.getPaginationSize();
	                    } else {
	                        fieldTotalPages = fieldTotalRecords / fieldPagination.getPaginationSize() + 1;
	                    }
	                    fieldPagination.setTotalPaginations(fieldTotalPages);
//	                    将集合属性的分页添加到cmiPagination中
//	                    cmiPagination
	                } catch (IllegalArgumentException | IllegalAccessException e) {
	                    // TODO Auto-generated catch block
	                    e.printStackTrace();
	                }
	            }
	        }
			return cmiPagination;
	    }

	    public <T> Map<String, CmiPagination> getReferencePaginationMap(T event)
				throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
			//		获取引用属性的分页对象；每一个引用属性就是一个fieleName-cmiPagination键值对
					Map<String, CmiPagination> referenceCmiPaginationMap = new HashMap<String, CmiPagination>();
			//		获取所有的集合域，CmiPagination对象采用默认的即可，默认的是每一页10个数据。
			//		--域名是：videosForEvent，类型是：cn.edu.scau.cmi.ema.domain.Video

					Map<String, Class<?>> collectionFieldPaginationMap = CmiEntityUtil.getCollectionFieldNameTypeMap(event.getClass());

					WebApplicationContext applicationContext = ContextLoader.getCurrentWebApplicationContext();

					Set<Entry<String,Class<?>>> collectionFieldTypeMapEntry = collectionFieldPaginationMap.entrySet();
					for(Entry<String, Class<?>> entry : collectionFieldTypeMapEntry) {
			//			fieldName: adultertypesForEvent,
			//			fieldClass: cn.edu.scau.cmi.ema.domain.Adultertype
						CmiPagination fieldPagination = new CmiPagination();

						String fieldName = entry.getKey();
						Class<?> fieldClass = entry.getValue();//具体的引用属性的分页
						System.out.println("域的名称：" + fieldName + "，实体类的名称：" + fieldClass);

						CmiPaginationService fieldPaginationService = (CmiPaginationService) applicationContext.getBean(fieldClass.getSimpleName() + "PaginationService");

						//该实体引用实体的总数量，分页拿出到前端
			//			使用命名查找？？？
			//			int entityQuantity = 100;
			//			再次通过反射的方法获取，但是有一个问题，会不会都查找到吗，然后影响效率，或者是采用命名方法查找？？？
			//			int entityQuantity = event.getEventsForParent().size();

						Method getReference = event.getClass().getMethod("get" + CmiStringUtil.convertFirstCharToUpper(fieldName));
						Set entityQuantities = (Set)getReference.invoke(event);
						System.out.println("域的数量是：" + entityQuantities.size());

						fieldPagination = fieldPaginationService.updatePagination(fieldPagination, entityQuantities.size() );

						System.out.println("<<<<<<<<<<<CmiPagination的名称：" + fieldPagination.getClass().getName());
						referenceCmiPaginationMap.put(fieldName, fieldPagination);
					}
			return referenceCmiPaginationMap;
		}

















}
